//
//  AFNetworkServices.m
//  YLNetworkingFrameworks
//
//  Created by Topsun on 16/6/2.
//  Copyright © 2016年 tcl. All rights reserved.
//

#import "AFNetworkServices.h"
#import "HTTPInterface.h"
#import "AFNetRequest.h"
#import "AFNetResponse.h"
#import "InstanceFactory.h"

@interface ResultBlock : NSObject

@property (nonatomic, copy) ResultHandler resultHandler;

@end

@implementation ResultBlock

- (id) initWithResultHandler:(ResultHandler) handler
{
    self = [super init];
    if ( self ) {
        self.resultHandler = handler;
    }
    return self;
}

@end

@interface ThreadEvnEntity : NSObject

@property (nonatomic, strong) AFNetRequest *netRequest;
@property (nonatomic, strong) NSObject *userInfo;
@property (nonatomic, assign) RequestPriority requestPriority;

@end

@implementation ThreadEvnEntity

@end

static AFNetworkServices *static_netWorkServices = nil;
static NSMutableArray *static_threadEvnInfo = nil;

@interface AFNetworkServices ()
{
    NSMutableDictionary *_threadEnvInfo;        // 线程间的通信的公用数据结构
    NSMutableArray *servicesInterfaceList;
    SEL requestsel;
}
@end

@implementation AFNetworkServices

+ (AFNetworkServices*) defaultNetWorkServices
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if( nil == static_netWorkServices ) {
            static_netWorkServices = [[AFNetworkServices alloc] init];
            static_threadEvnInfo = [[NSMutableArray alloc] init];
        }
    });
    
    return static_netWorkServices;
}

- (id) init
{
    self = [super init];
    if ( self != nil ) {
        requestsel = @selector(synSendRequest:);
    }
    return self;
}

// 发送一个异步网络请求
// 请求对象
// 发送成功返回YES，否则NO
- (BOOL) sendRequest:(AFNetRequest*) netRequest                   // 请求对象
         resultBlock:(ResultHandler)resultHandler
{
    ThreadEvnEntity *threadEvnInfo = [[ThreadEvnEntity alloc] init];
    
    threadEvnInfo.netRequest = netRequest;
    
    // 防止在异步过程中，修改该值（获取数据优先级）
    threadEvnInfo.requestPriority = netRequest.requestPriority;
    
    //
    ResultBlock * resultBlock = [[ResultBlock alloc] initWithResultHandler:resultHandler];
    threadEvnInfo.userInfo = resultBlock;
    
    [static_threadEvnInfo addObject:threadEvnInfo];
    
    dispatch_queue_t queue = dispatch_queue_create("com.Needs.YLNetworking", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(queue, ^{
        [self _sendRequest:threadEvnInfo];
    });
    
//    [self performSelectorInBackground:@selector(_sendRequest:) withObject:threadEvnInfo];
    
    return YES;
}

// 子线程入口函数，执行网络请求
// 请求对象
// 发送成功返回YES，否则NO
- (void) _sendRequest:(ThreadEvnEntity*) threadEvnInfo
{
    if ( [static_threadEvnInfo count] == 0 || threadEvnInfo == nil ) {
        return;
    }
    
    /*
     1、如果本地数据优先，则先从本地获取数据
     2、如果网络数据优先则先从网络获取数据: 如果网络优先情况下，没有网络则从本地获取数据
     */
    switch ( threadEvnInfo.requestPriority ) {
            
        case RequestPriorityDisk:
            [self performSelector:@selector(synSendRequestFormDisk:) withObject:threadEvnInfo];
            break;
            
        case RequestPriorityNetWork:
            // 如果没有网络，则从本地获取数据
            if ( requestsel == @selector(synSendRequestFormDisk:) ) {
                [self performSelector:@selector(synSendRequestFormDisk:) withObject:threadEvnInfo];
            } else {
                [self performSelector:@selector(synSendRequest:) withObject:threadEvnInfo];
            }
            break;
        default:
            break;
    }
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        if ([static_threadEvnInfo containsObject:threadEvnInfo])
        {
            [static_threadEvnInfo removeObject:threadEvnInfo];
        }
    });
}

// 从网络请求数据
- (void) synSendRequest:(ThreadEvnEntity*) threadEvnEntity
{
    // 获取一个http请求接口对象
    HttpAsynInterface httpSynInterface = [InstanceFactory getHttpAsynInterface];
    HttpInterface httpInterface = httpSynInterface;
    
    // 开始发送http请求（未设置参数）
    [self startSendNetRequest:threadEvnEntity.netRequest ProgressStat:eStart additionInfo:nil];
    
    // 设置http请求地址
    httpInterface.url = threadEvnEntity.netRequest.requestURL;
    
    // 设置http请求方式：GET POST
    [httpSynInterface setRequestMethod:threadEvnEntity.netRequest.requestMethod];
    
    // 设置http Post请求参数
    if ([[threadEvnEntity.netRequest.parameterEntity.postDictionary allKeys]count]>0) {
        [self setPOSTParameters:threadEvnEntity httpInterface:httpInterface];
    }
    
    // 设置http Get请求参数
    if ([[threadEvnEntity.netRequest.parameterEntity.getDictionary allKeys]count]>0) {
        [self setGETParameters:threadEvnEntity httpInterface:httpInterface];
    }
    
    // 设置http头部信息
    if ([[threadEvnEntity.netRequest.parameterEntity.headDictionary allKeys]count]>0) {
        [self setHEADParameters:threadEvnEntity httpInterface:httpInterface];
    }
    
    // 参数设置完成
    [self startSendNetRequest:threadEvnEntity.netRequest ProgressStat:eDoneParameter additionInfo:nil];
    
    __weak AFNetworkServices * weakSelf = self;
    
    //使用AFNetWorking异步请求网络
    [httpSynInterface startAsynchronous:^(id resultSource)
     {
         // 网络请求完成,处理网络数据
         [weakSelf handleCompletionRequest:resultSource threadEntity:threadEvnEntity httpInterface:httpInterface];
     }];
}

// 网络请求完成,处理网络数据
-(void)handleCompletionRequest:(id)resultJsonStr threadEntity:(ThreadEvnEntity*) threadEvnEntity httpInterface:(HttpInterface) httpInterface
{
    // http请求发送完成
    [self startSendNetRequest:threadEvnEntity.netRequest ProgressStat:eDoneRequest additionInfo:httpInterface.responseString];
    
    // 如果从网络获取不到数据，并且该接口要存储到本地，则从本地磁盘获取一次数据
    if ( httpInterface.responseString == nil && threadEvnEntity.netRequest.isSerialize )
    {
        // 如果不是本地数据优先，则在从本地获取数据
        if ( threadEvnEntity.requestPriority == RequestPriorityNetWork )
        {
            [self performSelector:@selector(synSendRequestFormDisk:) withObject:threadEvnEntity];
        }
        return;
    }
    
#ifdef DEBUG
  // 输出网络回传数据
  [self printNetworkReturnBackData:threadEvnEntity httpInterface:httpInterface];
#endif

    ResultBlock * resultBlock = (ResultBlock*)threadEvnEntity.userInfo;
    
    if ( httpInterface.error != nil || httpInterface.responseString == nil)
    {
        // http请求失败
        dispatch_async(dispatch_get_main_queue(), ^{
            resultBlock.resultHandler(threadEvnEntity.netRequest,threadEvnEntity.netRequest.netResponse,httpInterface.error);
        });
        
    } else {
        
        // 创建响应对象
        AFNetResponse * netResponse = [[AFNetResponse alloc] initWithJson:httpInterface.responseString];
        
        // 设置数据来源
        netResponse.netResponseFromType = eNetResponseFromNetWork;
        
        // 设置请求对象的响应对象
        threadEvnEntity.netRequest.netResponse = netResponse;
        
        // http请求发送完成，并创建了响应对象
        [self startSendNetRequest:threadEvnEntity.netRequest ProgressStat:eRequestComplete additionInfo:threadEvnEntity.userInfo];
        
        // 在主线程中通知
        dispatch_async(dispatch_get_main_queue(), ^{

            resultBlock.resultHandler(threadEvnEntity.netRequest,threadEvnEntity.netRequest.netResponse,nil);
        });
    }
}

// 从硬盘中读取数据
- (void) synSendRequestFormDisk:(ThreadEvnEntity*) threadEvnEntity
{

}

- (NSObject*) startSendNetRequest:(AFNetRequest*) netRequest                   // 正在出来的NetRequest对象
                     ProgressStat:(XProgressStat) stat                       // 当前进度状态
                     additionInfo:(NSObject*) additionInfo                   // 附加参数，不同进度状态下，参数值有所不同
{
    
    for ( id<NetWorkServicesInterface> interface in servicesInterfaceList ) {
        if ( [interface respondsToSelector:@selector(netWorkServices:startSendNetRequest:ProgressStat:additionInfo:)] ) {
            [interface netWorkServices:self startSendNetRequest:netRequest ProgressStat:stat additionInfo:additionInfo];
        }
    }
    
    return nil;
}

// 设置http Post请求参数
- (void)setPOSTParameters:(ThreadEvnEntity*)threadEvnEntity httpInterface:(HttpInterface)httpInterface
{
    for (NSString *key in [threadEvnEntity.netRequest.parameterEntity.postDictionary allKeys] ) {
        
        id<NSObject> value = [threadEvnEntity.netRequest.parameterEntity.postDictionary objectForKey:key];
        
        [httpInterface addPostValue:value forKey:key];
    }
}

// 设置http Get请求参数
- (void)setGETParameters:(ThreadEvnEntity*)threadEvnEntity httpInterface:(HttpInterface)httpInterface
{
    // 设置http Get请求参数
    for (NSString *key in [threadEvnEntity.netRequest.parameterEntity.getDictionary allKeys] ) {
        
        id<NSObject> value = [threadEvnEntity.netRequest.parameterEntity.getDictionary objectForKey:key];
        
        [httpInterface addGetValue:value forKey:key];
    }
}

// 设置http头部信息
- (void)setHEADParameters:(ThreadEvnEntity*)threadEvnEntity httpInterface:(HttpInterface)httpInterface
{
    for ( NSString *key in [threadEvnEntity.netRequest.parameterEntity.headDictionary allKeys] ) {
        
        id<NSObject> value = [threadEvnEntity.netRequest.parameterEntity.headDictionary objectForKey:key];
        
        [httpInterface addHeadValue:value forKey:key];
    }
}

// 添加监听
- (void) addInterfaceLister:(id<NetWorkServicesInterface>) interface
{
    if ( nil == servicesInterfaceList ) {
        servicesInterfaceList = [[NSMutableArray alloc] init];
    }
    
    if ( interface != nil ) {
        [servicesInterfaceList addObject:interface];
    }
}

// 移除监听
- (void) removeInterfaceLister:(id<NetWorkServicesInterface>) interface
{
    if ( interface != nil ) {
        [servicesInterfaceList removeObject:interface];
    }
}

/**
 *  @author 李悦麟, 16-06-03
 *
 *  输出网络回传数据
 *
 *  @param threadEvnEntity
 *  @param httpInterface
 *
 *  @since 1.0
 */
-(void)printNetworkReturnBackData:(ThreadEvnEntity*)threadEvnEntity httpInterface:(HttpInterface)httpInterface
{
    NSError *parseError = nil;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:threadEvnEntity.netRequest.parameterEntity.postDictionary options:NSJSONWritingPrettyPrinted error:&parseError];
    NSString *string = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    NSLog(@"********************************************************");
    NSLog(@"####### %@", threadEvnEntity.netRequest.requestTypeKey);
    if ( string == nil )
    {
        NSLog(@"####### Request:%@", threadEvnEntity.netRequest.parameterEntity.postDictionary);
    } else {
        NSLog(@"####### Request:%@", string);
    }
    NSLog(@"####### %@ Response:%@", threadEvnEntity.netRequest.requestTypeKey, httpInterface.responseString);
    NSLog(@"********************************************************");
}

@end
